package cn.wolfcode.service.impl;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.common.web.anno.RequireLogin;
import cn.wolfcode.domain.*;
import cn.wolfcode.fegin.PabByintergralApi;
import cn.wolfcode.fegin.PayFeginApi;
import cn.wolfcode.mapper.OrderInfoMapper;
import cn.wolfcode.mapper.PayLogMapper;
import cn.wolfcode.mapper.RefundLogMapper;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMessage;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.IdGenerateUtil;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by wolfcode-lanxw
 */
@Service
public class OrderInfoSeviceImpl implements IOrderInfoService {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private PayLogMapper payLogMapper;
    @Autowired
    private RefundLogMapper refundLogMapper;
    @Qualifier("cn.wolfcode.fegin.PayFeginApi")
    @Autowired
    private PayFeginApi payFeginApi;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Qualifier("cn.wolfcode.fegin.PabByintergralApi")
    @Autowired
    private PabByintergralApi paybByintergralApi;
    
    @Value("${pay.returnUrl}")
    private String returnUrl;
    
    @Value("${pay.notifyUrl}")
    private String notifyUrl;
    
    
    @RequireLogin
    @Transactional
    @Override
    public String order(OrderMessage orderMessage) {
//        2)判断库存是否已经卖完
      SeckillProduct product= seckillProductService.findfromDB(orderMessage.getSeckillId());
      if (product.getStockCount()<=0){
          throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
      }
//        3)是否是重复下单
        Long phone = orderMessage.getUserPhone();
        Integer seckillId = Math.toIntExact(orderMessage.getSeckillId());
        OrderInfo orderInfo=orderInfoMapper.findByPhoneAndSeckillId(phone, seckillId);
        if (orderInfo!=null){
            //说明重复下单
            throw new BusinessException(SeckillCodeMsg.REPEAT_SECKILL);
        }
        SeckillProductVo productVo = seckillProductService.find(orderMessage.getTime(), seckillId);
//        4)增加订单信息
        OrderInfo info=new OrderInfo();
        //雪花算法
        info.setOrderNo(String.valueOf(IdGenerateUtil.get().nextId()));
        info.setUserId(phone);
        info.setProductId(productVo.getProductId());
       // info.setDeliveryAddrId(0L);
        info.setProductName(productVo.getProductName());
        info.setProductImg(productVo.getProductImg());
        info.setProductCount(1);
        info.setProductPrice(productVo.getProductPrice());
        info.setSeckillPrice(productVo.getSeckillPrice());
        info.setIntergral(productVo.getIntergral());
        info.setStatus(OrderInfo.STATUS_ARREARAGE);
        info.setCreateDate(new Date());
     //   info.setPayDate(new Date());
      //  info.setPayType(0);
        info.setSeckillDate(new Date());
        info.setSeckillTime(orderMessage.getTime());
        info.setSeckillId(orderMessage.getSeckillId());
        orderInfoMapper.insert(info);
//        5)真实库存-1
        seckillProductService.descContOne(orderMessage.getSeckillId());


        return info.getOrderNo();
    }
    
    @Override
    public OrderInfo findOrderByOrderNo(String orderNo) {
        return orderInfoMapper.find(orderNo);
    }
    
    @Override
    public void changeOrderStatus(String orderNo,  Integer statusTimeout) {
        orderInfoMapper.updateCancelStatus(orderNo,statusTimeout);
    }
    
    @RequireLogin
    @Transactional
    @Override
    public String payOnLine(String orderNo) {
        //查询订单信息
        OrderInfo info = orderInfoMapper.find(orderNo);
        //日志操作
        PayLog payLog = new PayLog();
        payLog.setTradeNo(orderNo);
        payLog.setOutTradeNo("");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String date = simpleDateFormat.format(new Date());
        payLog.setNotifyTime(date);
        payLog.setTotalAmount(String.valueOf(info.getSeckillPrice()));
        payLog.setPayType(OrderInfo.PAYTYPE_ONLINE);
        payLogMapper.insert(payLog);
        //远程调用支付服务，进行支付操作
        PayVo payVo = new PayVo();
        payVo.setOutTradeNo(orderNo);
        payVo.setTotalAmount(info.getSeckillPrice().toString());
        payVo.setSubject(info.getProductName());
        payVo.setBody("秒杀");
        payVo.setReturnUrl(returnUrl);
        payVo.setNotifyUrl(notifyUrl);
        
        
        Result<String> result= payFeginApi.payOnlin(payVo);
        if (result==null||result.hasError()){
            throw  new BusinessException(SeckillCodeMsg.PAY_SERVER_ERROR);
        }
        
        return result.getData();
    }
    
    @Override
    public String notifyService(Map<String, String> params) {
        //success||fall
        //验签
 Result<Boolean>result=  payFeginApi.valIdatasign(params);
        //成功修改订单状态为已支付
    if (result.getData()){
        //获取订单编号
        String outTradeNo = params.get("out_trade_no");
        int i = orderInfoMapper.changePayStatus(outTradeNo, OrderInfo.STATUS_ACCOUNT_PAID, OrderInfo.PAYTYPE_ONLINE);
        String tradeNo = params.get("trade_no");
        PayLog payLog = new PayLog();
        payLog.setOutTradeNo(tradeNo);
        payLog.setTradeNo(outTradeNo);
        rocketMQTemplate.sendOneWay(MQConstant.PAY_ZFB,payLog);
        return i>0?"success":"fall";
    }else {
        return "fall";
    }
   }
    
    
    @RequireLogin
    @Override
    public Boolean returnService(Map<String, String> params) {
        //
        //验签
        Result<Boolean>result=  payFeginApi.valIdatasign(params);
        return result.getData();
    }
    @GlobalTransactional
    @Override
    public Boolean refund(String orderNo) {
        //通过orderNo获得订单信息
        OrderInfo info = orderInfoMapper.find(orderNo);
        if (info.getPayType()==OrderInfo.PAYTYPE_ONLINE){
            //在线退款
            return refundOnLine(info);
        }else {
            //积分退款
            return  refundInternal(info,null);
        }
        //根据type 进行退款
        

    }
    
    @RequireLogin
    private Boolean refundInternal(OrderInfo info,BusinessActionContext context) {
        
        //退款日志
        RefundLog refundLog = new RefundLog();
        refundLog.setOutTradeNo(info.getOrderNo());
        refundLog.setRefundAmount(info.getSeckillPrice().toString());
        refundLog.setRefundReason("芜1湖");
        refundLog.setRefundType(OrderInfo.PAYTYPE_INTERGRAL);
        refundLog.setRefundTime(new Date());
        refundLogMapper.insert(refundLog);
    //远程调用
        OperateIntergralVo intergralVo = new OperateIntergralVo();
        intergralVo.setPk(info.getOrderNo());
        intergralVo.setValue(info.getIntergral());
        intergralVo.setInfo(info.getProductName());
        intergralVo.setUserId(info.getUserId());
        Result<Boolean>  ret= paybByintergralApi.refundOnintergral(intergralVo);
        if (ret==null||ret.hasError()){
            throw new BusinessException(SeckillCodeMsg.REFUND_ERROR);
        }
        if (ret.getData()){
            //修改订单状态
            int i = orderInfoMapper.changeRefundStatus(info.getOrderNo(), OrderInfo.STATUS_REFUND);
            ret.setData(i>0);
        }
        return  ret.getData();
        
    }
    
    
    @RequireLogin
    private Boolean refundOnLine(OrderInfo info) {
        //退款日志
        RefundLog refundLog = new RefundLog();
        refundLog.setOutTradeNo(info.getOrderNo());
        refundLog.setRefundAmount(info.getSeckillPrice().toString());
        refundLog.setRefundReason("芜1湖");
        refundLog.setRefundType(OrderInfo.PAYTYPE_ONLINE);
        refundLog.setRefundTime(new Date());
        refundLogMapper.insert(refundLog);
        
        PayLog payLog = payLogMapper.getById(info.getOrderNo());
    
        RefundVo refundVo = new RefundVo();
        refundVo.setTradeNo(payLog.getOutTradeNo());
        refundVo.setOutTradeNo(info.getOrderNo());
        refundVo.setRefundAmount(info.getSeckillPrice().toString());
        refundVo.setRefundReason("芜湖");
        
      Result<Boolean>  ret= payFeginApi.refundOnLine(refundVo);
      if (ret==null||ret.hasError()){
          throw new BusinessException(SeckillCodeMsg.REFUND_ERROR);
      }
      if (ret.getData()){
          //修改订单状态
          rocketMQTemplate.syncSend(MQConstant.PAY_ZFB_REFUND,info.getOrderNo());
      }
      return  ret.getData();
    }
    @GlobalTransactional
    @Override
    public String payByIntergral(String orderNo) {
        //支付日志
        //查询订单信息
        OrderInfo info = orderInfoMapper.find(orderNo);
        //日志操作
        PayLog payLog = new PayLog();
        payLog.setTradeNo(orderNo);
        payLog.setOutTradeNo("");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String date = simpleDateFormat.format(new Date());
        payLog.setNotifyTime(date);
        payLog.setTotalAmount(String.valueOf(info.getSeckillPrice()));
        payLog.setPayType(OrderInfo.PAYTYPE_INTERGRAL);
        payLogMapper.insert(payLog);
        //积分服务调用
        OperateIntergralVo intergralVo = new OperateIntergralVo();
        intergralVo.setPk(info.getOrderNo());
        intergralVo.setValue(info.getIntergral());
        intergralVo.setInfo(info.getProductName());
        intergralVo.setUserId(info.getUserId());
        
       Result<Boolean> ret= paybByintergralApi.payOnIntergral(intergralVo);
        
        //修改订单状态
        if (ret==null||ret.hasError()){
            throw new BusinessException(SeckillCodeMsg.REFUND_ERROR);
        }
        if (ret.getData()){
        //修改订单状态
        orderInfoMapper.changePayStatus(info.getOrderNo(),OrderInfo.STATUS_ACCOUNT_PAID,OrderInfo.PAYTYPE_INTERGRAL);
        }
        return "";
    }
}
